﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace BaiTap1
{
    public abstract class BieuThuc
    {
        public abstract double TinhGiaTri(double x);
        public abstract string TinhDaoHam();
        public static double[] DocTapTin(string fileName)
        {
            string[] lines = System.IO.File.ReadAllLines(fileName);
            double[] result = new double[lines.Count()];
            int i = 0;
            foreach (string line in lines)
            {
                result[i++] = double.Parse(line);
                //Console.WriteLine("\t" + line);
            }
            return result;
        }
        public static void ChuyenSangBieuThuc(ref BieuThuc bieuThuc, double[] num, ref int curr)
        {            
            BieuThuc bt = null;            
            //Xử lý để lấy ra biểu thức
            if (num[curr] == 0)    //Biểu thức hằng
            {
                bt = new BieuThucDon(num[++curr]);
                curr++;
            }
            else if (num[curr] == 1)   //Biểu thức đơn
            {                
                bt = new BieuThucDon((int)num[curr + 2], num[curr + 1]);
                curr += 3;
            }
            else if (num[curr] == 2)   //Biểu thức tổng
            {
                curr++;
                bt = new BieuThucTong();                
                BieuThuc.ChuyenSangBieuThuc(ref bt, num, ref curr); //u
                BieuThuc.ChuyenSangBieuThuc(ref bt, num, ref curr); //v
            }
            else if (num[curr] == 3)   //Biểu thức tích
            {
                curr++;
                bt = new BieuThucTich();                
                BieuThuc.ChuyenSangBieuThuc(ref bt, num, ref curr); //u
                BieuThuc.ChuyenSangBieuThuc(ref bt, num, ref curr); //v
            }
            else if (num[curr] == 4)   //Biểu thức chia
            {
                curr++;
                bt = new BieuThucChia();                
                BieuThuc.ChuyenSangBieuThuc(ref bt, num, ref curr); //u
                BieuThuc.ChuyenSangBieuThuc(ref bt, num, ref curr); //v
            }            
            //Gán biểu thức con vào biểu thức cha
            if (bieuThuc == null)
            {
                bieuThuc = bt;
            }
            else
            {
                if (bieuThuc is BieuThucTong)
                {
                    ((BieuThucTong)bieuThuc).GanBieuThuc(bt);
                }
                else if (bieuThuc is BieuThucTich)
                {
                    ((BieuThucTich)bieuThuc).GanBieuThuc(bt);
                }
                else if (bieuThuc is BieuThucChia)
                {
                    ((BieuThucChia)bieuThuc).GanBieuThuc(bt);
                }
            }
        }

        public static void XuLyCach1()
        {
            //Đọc tất cả các số được nhập
            Console.Out.WriteLine("Please type input (seperate by space, press enter to finish): ");
            string input = Console.ReadLine();
            string[] inputs = input.Split(' ');
            double[] num = new double[inputs.Count()];
            for (int i = 0; i < inputs.Count(); ++i)
            {
                num[i] = int.Parse(inputs[i]);   
            }
            //Chuyển số thành biểu thức
            BieuThuc bt = null;
            int curr = 0;
            BieuThuc.ChuyenSangBieuThuc(ref bt, num, ref curr);
            //Tính giá trị và đạo hàm
            double kq = bt.TinhGiaTri(num[num.Count() - 1]);
            string daoHam = bt.TinhDaoHam();
            //Xử lý "+ -1" thành "- 1"
            daoHam = daoHam.Replace("+ -", "- ");
            Console.Out.WriteLine(kq);
            Console.Out.WriteLine(daoHam);
        }
        public static void XuLyCach2(string fileInput, string fileOutput)
        {
            //Đọc tất cả các số trong tập tin
            double[] num = BieuThuc.DocTapTin(fileInput);
            //Chuyển số thành biểu thức
            BieuThuc bt = null;
            int curr = 0;
            BieuThuc.ChuyenSangBieuThuc(ref bt, num, ref curr);
            //Tính giá trị và đạo hàm
            double kq = bt.TinhGiaTri(num[num.Count() - 1]);
            string daoHam = bt.TinhDaoHam();
            //Xử lý "+ -1" thành "- 1"
            daoHam = daoHam.Replace("+ -", "- ");
            //Ghi kết quả ra tập tin
            TextWriter tw = new StreamWriter(fileOutput);
            tw.WriteLine(kq);
            tw.WriteLine(daoHam);
            tw.Close();
        }

        public static BieuThuc ConvertFromString(string input)
        {
            BieuThuc bieuThuc = null;
            string s = input;
            Stack<string> firstStack = new Stack<string>();
            Stack<BieuThuc> secondStack = new Stack<BieuThuc>();
            while (s != string.Empty)
            { 
                if(LaToanHang(s[0].ToString()))
                {
                
                }
                else if(LaToanTu(s[0].ToString()))
                {
                
                }
                else if (s[0] == '(')
                {
                    firstStack.Push("(");
                }
                else if (s[0] == ')')
                {
                    string first = firstStack.First();
                    while (first != "(")
                    {
                        
                    }
                }
            }
            return bieuThuc;
        }
        public static bool LaToanHang(string s)
        {
            double Num;
            bool isNum = double.TryParse(s, out Num);
            return isNum;            
        }
        public static bool LaToanTu(string s)
        {
            if (s == "+" || s == "-" || s == "*" || s == "/")
                return true;
            return false;
        }
        public bool SoSanh(char a, char b)
        {
            if (a == '*' || a == '/')
                return true;
            if (a == '+' || a == '-')
            {
                if ((b == '*') || (b == '/'))
                    return false;
                return true;
            }
            return false;
        }
    }
}
